/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
// l24scrn.hpp - Linear screen driver for 24-bpp (16M color) operation.
//
// Author: Jarret M. Gill
//
// Copyright (c) 2006 Swell Software, Inc.
//              All Rights Reserved.
//
// Unauthorized redistribution of this source code, in whole or part,
// without the express written permission of Swell Software
// is strictly prohibited.
//
// Notes:
//
// This is a byte oriented, packed 24bpp format screen driver.
//
// The driver can run in either R:G:B  format,
// or the driver can run in B:G:R  format.
//
// In most cases the color order does not matter to the driver, it simply
// copies colors in the format provided by WindowBuilder. However for
// 24-bpp images with Alpha channel, the driver has to know of the Alpha
// value is the first or last byte of each 4-byte pixel group.
//
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef _L24SCREEN_
#define _L24SCREEN_


/*--------------------------------------------------------------------------*/
// RGB macros - Useful for obtaining color components in either RGB
// or BGR formats
/*--------------------------------------------------------------------------*/

#define REDVAL(c)    ((PEGUBYTE) (((PEGULONG)c) >> 16))
#define GREENVAL(c)  ((PEGUBYTE) ((((PEGULONG)c) >> 8) & 0xff))
#define BLUEVAL(c)   ((PEGUBYTE) (((PEGULONG)c) & 0xff))

#define MakeTrueColor(r, g, b) (((r) << 16) | ((g) << 8) | (b))


/*--------------------------------------------------------------------------*/
// Blend - Combines two color components (c1, c2) using an alpha ratio
/*--------------------------------------------------------------------------*/
#define BLEND(c1, c2, a) (PEGUBYTE)((((c1) * (a)) + ((c2 * (256 - (a))))) >> 8)

/*--------------------------------------------------------------------------*/
// BlendRGB - Combines the specified R, G, B components with whatever 
// color is already in the buffer at location pPut.  Note that this
// macro requires a variable named pPut to be pointing at a valid location.
/*--------------------------------------------------------------------------*/
#ifndef PEG_BGR_ORDER
#define BlendRGB(_r, _g, _b, _a) \
        { \
        *pPut = BLEND((_r), *pPut, (_a)); \
        pPut++; \
        *pPut = BLEND((_g), *pPut, (_a)); \
        pPut++; \
        *pPut = BLEND((_b), *pPut, (_a)); \
        pPut++; \
        }
#else
#define BlendRGB(_r, _g, _b, _a) \
        { \
        *pPut = BLEND((_b), *pPut, (_a)); \
        pPut++; \
        *pPut = BLEND((_g), *pPut, (_a)); \
        pPut++; \
        *pPut = BLEND((_r), *pPut, (_a)); \
        pPut++; \
        }
#endif

/*--------------------------------------------------------------------------*/
// Draws the specified color components onto the screen.  Note that
// this macro requires a variable named pPut to be pointing to a valid
// location.
/*--------------------------------------------------------------------------*/
#ifndef PEG_BGR_ORDER
#define WriteRGBColor(_r, _g, _b) \
        { \
        *pPut++ = (_r); \
        *pPut++ = (_g); \
        *pPut++ = (_b); \
        }

#else
#define WriteRGBColor(_r, _g, _b) \
        { \
        *pPut++ = (_b); \
        *pPut++ = (_g); \
        *pPut++ = (_r); \
        }
#endif


/*--------------------------------------------------------------------------*/
// CopyColor - Retrieves all 3 components of a color from pGet and draws
// them into pPut.  Note that this macro requires both variables pPut and
// pGet to be pointing to valid locations.
/*--------------------------------------------------------------------------*/
#define CopyColor() \
        { \
        *pPut++ = *pGet++; \
        *pPut++ = *pGet++; \
        *pPut++ = *pGet++; \
        }



/*--------------------------------------------------------------------------*/
#ifndef PEG_PLOTPOINTVIEW_AS_FUNCTION
#ifndef PEG_BGR_ORDER
#define PlotPointView(x, y, c) \
        { \
        PEGUBYTE *_pPut = (PEGUBYTE *) SCANLINESTART(y) + ((x) * 3); \
        *_pPut++ = REDVAL(c); \
        *_pPut++ = GREENVAL(c); \
        *_pPut = BLUEVAL(c); \
        }

#else
#define PlotPointView(x, y, c) \
        { \
        PEGUBYTE *_pPut = (PEGUBYTE *) SCANLINESTART(y) + ((x) * 3); \
        *_pPut++ = BLUEVAL(c); \
        *_pPut++ = GREENVAL(c); \
        *_pPut = REDVAL(c); \
        }
#endif

#endif

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
class L24Screen : public PegScreen
{
    public:
        L24Screen(const PegRect &);
        virtual ~L24Screen();

        virtual void Capture(PegCapture *Info, PegRect &Rect);

        virtual PegBitmap *CreateBitmap(PEGINT Width, PEGINT Height,
            PEGINT Style = BMF_RAW|BMF_HAS_TRANS);

        virtual PEGUBYTE *GetPalette(PEGULONG *pPutSize);

       #ifdef PEG_IMAGE_SCALING
        virtual PEGCOLOR GetBitmapPixel(PEGINT x, PEGINT y, PegBitmap *pMap)
        {
            PEGCOLOR cVal;
            PEGUBYTE *pGet = pMap->pStart;
            pGet += pMap->Width * y * 3;
            pGet += x * 3;
            cVal = *pGet++;
            cVal <<= 8;
            cVal |= *pGet++;
            cVal <<= 8;
            cVal |= *pGet;
            return cVal;
        }
       #endif

        virtual PEGCOLOR GetPixelView(PEGINT x, PEGINT y)
        {
            if (mpContext)
            {
                PEGCOLOR cVal;
                PEGUBYTE *pGet = (PEGUBYTE *) SCANLINESTART(y) + (x * 3);

                cVal = *pGet++;
                cVal <<= 8;
                cVal |= *pGet++;
                cVal <<= 8;
                cVal |= *pGet;
                return cVal;
            }
            else
            {
                return 0;
            }
        }

       #ifdef PEG_IMAGE_SCALING
        virtual void PutBitmapPixel(PEGINT x, PEGINT y, PegBitmap *pMap, 
                                    PEGCOLOR Val)
        {
          if (pMap->BitsPix == 24)
          {
             PEGUBYTE *pPut = pMap->pStart;
             pPut += pMap->Width * y * 3;
             pPut += x * 3;

             *pPut++ = (PEGUBYTE) (Val >> 16);
             *pPut++ = (PEGUBYTE) (Val >> 8);
             *pPut = (PEGUBYTE) Val;
          }
        }
       #endif

        virtual void ResetPalette(void);
        virtual void SetPalette(PEGINT First, PEGINT Num, 
                                const PEGUBYTE *pGet);

    protected:

       #ifdef PEG_AA_LINE
        virtual void AALineView(PEGINT xStart, PEGINT yStart, PEGINT xEnd, 
                                PEGINT yEnd, const PegRect &View, PegBrush &Brush);
       #endif

        virtual void BitmapView(const PegPoint Where, 
                                const PegBitmap *pGetmap, 
                                const PegRect &View);

       #if defined(PEG_MULT_SOFT_SURFACES)

        void BlendSurface(DrawSurface *pSurface, PegRect &Copy,
            PEGUBYTE *pComposite);

        PEGBOOL BuildCompositeSurface(PegRect &Copy, PEGUBYTE *pComposite);

        void CopySurface(DrawSurface *pSurface, PegRect &Copy,
            PEGUBYTE *pComposite);

       #endif

       #ifdef PEG_AA_FONT
        virtual void DrawSimpleAliasedText(PegPoint Where, const PEGCHAR *pText, 
                                     PegBrush &Brush, const PegFont *pFont, 
                                     PEGINT Count, PegRect &Rect);

       #if defined(PEG_TRUE_ALIAS)
        virtual void DrawTrueAliasedText(PegPoint Where, const PEGCHAR *pText, 
                               PegBrush &Brush, const PegFont *pFont, 
                               PEGINT Count, PegRect &Rect);

        virtual void DrawAliasedTextToAlphaMap(PegPoint Where,
                const PEGCHAR *pText, PegBrush &Brush, const PegFont *pFont,
                PEGINT Count, PegRect &Clip);
       #endif
       #endif

       #ifdef PEG_PRO
        virtual void DrawAliasMapView(PegPoint Where, const PegBitmap *pMap,
            PegBrush &Brush, const PegRect &View);
       #endif

       #ifdef PEG_OUTLINE_FONT
        virtual void DrawOutlineText(PegPoint Where, const PEGCHAR *pText, 
                                     PegBrush &Brush, const PegFont *pFont, 
                                     PEGINT Count, PegRect &Rect);
       #endif

       #ifdef PEG_FREETYPE_SUPPORT
        virtual void DrawFreetypeAliasedText(PegPoint Where, const PEGCHAR *pText,
            PegBrush &Brush, const PegFont *pFont, PEGINT Count, PegRect &Clip);

        virtual void DrawFreetypeBinaryText(PegPoint Where, const PEGCHAR *pText,
            PegBrush &Brush, const PegFont *pFont, PEGINT Count, PegRect &Clip);
       #endif

        virtual void DrawRleBitmap(const PegPoint Where, const PegRect &View,
                                   const PegBitmap *pGetmap);

        virtual void DrawTextView(PegPoint Where, const PEGCHAR *pText, 
                                  PegBrush &Brush, const PegFont *pFont, 
                                  PEGINT Count, PegRect &Rect);

        virtual void DrawTrueColorBitmap(const PegPoint Where, 
                                         const PegRect &View,
                                         const PegBitmap *pGetmap);

        virtual void DrawTrueColorAlphaBitmap(const PegPoint Where,
                                              const PegRect &View,
                                              const PegBitmap *pGetMap);

        virtual PEGUBYTE *GetVideoAddress(void);
        virtual void HorizontalLine(PEGINT XStart, PEGINT XEnd, PEGINT YPos,
                                    PEGCOLOR Color, PEGINT Width);
        virtual void HorizontalLineXOR(PEGINT XStart, PEGINT XEnd, 
                                       PEGINT YPos);
       #ifdef PEG_BIDI_SUPPORT
        virtual PEGINT LatinTextLength(PEGCHAR *pText);
       #endif
        virtual void LineView(PEGINT xStart, PEGINT yStart, PEGINT xEnd, 
                              PEGINT yEnd, PegRect &Rect, PegBrush &Brush);

        void MakeAAColors(PEGUBYTE *PutColors, PegBrush &Brush);

        virtual void PlotSubPixel(PegFixed xVal, PegFixed yVal, PEGCOLOR Color);

        virtual void RectMoveView(const PegRect &View,
                                  const PEGINT xMove, const PEGINT yMove);

       #ifdef PEG_PRO
        PEGCOLOR TrueAlias(PEGCOLOR Back, PEGCOLOR Fore, PEGINT Blend);
        void PlotTrueAlias(PEGUBYTE *Where, PEGCOLOR Fore, PEGINT Blend);

       #ifdef PEG_AA_LINE
        virtual void TrueAliasLineView(PEGINT xStart, PEGINT yStart, PEGINT xEnd, 
                                PEGINT yEnd, const PegRect &View, PegBrush &Brush);
       #endif
       #endif // PEG_PRO

        virtual void VerticalLine(PEGINT YStart, PEGINT YEnd, PEGINT XPos,
                                  PEGCOLOR Color, PEGINT Width);
        virtual void VerticalLineXOR(PEGINT YStart, PEGINT YEnd, PEGINT XPos);


        PEGUBYTE mPalette[256 * 3];  // palette for drawing 8bpp bitmaps
};

#endif



